# -*- coding: utf-8 -*-
"""
Created on Wed Feb  3 21:28:18 2021
tk matplotlib
@author: 59567
"""
import os
import shutil

import pandas as pd
import yaml
import numpy as np
import matplotlib.pyplot as plt
# -------------------------------------------------------------------------------------------
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.backend_bases import key_press_handler
# ------------------------------------------------------------------------------------------
import tkinter as tk
from tkinter import Frame, Label, Text, StringVar, Button, END
from tkinter.ttk import Combobox, Spinbox
from tkinter.filedialog import askdirectory
from tkinter.simpledialog import askfloat
from copy import deepcopy
from tjdutils.utils import check_path, save_pickle, real_path, load_pickle, exists
from tjdutils.fractal_dimension import calculate_fractal_dimension as cal_fd
from tjdutils.files_operation import del_output_trainer_y, input_x_pkls
# ------------------------------------------------------------------------------------------
from gui.tk_mpl_utils import expend_dimension, prepare_y_yp_acc, plot_fill_between
from gui.tk_mpl_utils import get_month_end_real
from pandas import read_pickle, date_range, DataFrame, read_excel, concat, to_datetime, Series
from matplotlib.figure import Figure
from itertools import combinations as cb
from collector.metrics import Metrics
from monitor.hf_monitor import Monitor
from monitor.corrector import Corrector
from matplotlib.backends.backend_pdf import PdfPages
from PyPDF2 import PdfFileReader as reader
from PyPDF2 import PdfFileWriter as writer

plt.rcParams['font.sans-serif'] = ['SimHei']  # 中文显示
plt.rcParams['axes.unicode_minus'] = False  # 负号显示


def show_some_text(s):
    tk.messagebox.showinfo('提示', s)


def show_some_input():
    s = tk.filedialog.askopenfilename(title='请选择你要上传的文件')
    return s


def load_config():
    with open("gui/mpl_config.yaml", 'r', encoding='utf-8') as f:
        data = yaml.load(f.read(), Loader=yaml.FullLoader)
    return data


class From():
    def __init__(self):
        super(From, self).__init__()
        self._basic_ini_()
        self.config = load_config()
        self.root = tk.Tk()  # 创建主窗体
        self.root.title("欢迎使用高频模拟后台")
        self.root.geometry("1850x1000")
        self.bg = "CornflowerBlue"  # 设置背景色
        self.m_f = ('Microsoft YaHei', 20,)  # main_font, 主要字体
        self.s_f = ('Microsoft YaHei', 15,)  # second_font, 二级字体
        self.t_f = ('Microsoft YaHei', 12,)  # third_font, 三级字体
        self.canvas = tk.Canvas()  # 创建一块显示图形的画布
        self.tool_ready = False
        self.correct = False
        self.metrics = {'rolling_acc': False, 'triangle_area': True,
                        'test_mse': True, 'test_mae': True, 'test_vbp': False}
        self.y = read_excel(real_path('y集合.xlsx'), index_col=0)
        self.x = read_pickle(real_path(input_x_pkls()[0]))
        self.summary = None
        self.hf_df = None
        self.correct_hf_df = None
        self.save_fig = {}
        self.select_feature = []

        self.upper_plot_args = 'cent'
        self.lower_plot_args = 'rolling'

        self.fm_args = Frame(self.root, height=720, width=390, relief='ridge', bd=5, bg=self.bg)
        self.fm_args.place(x=10, y=10)
        self.fm_print = Frame(self.root, height=200, width=390, relief='ridge', bd=5, bg=self.bg)
        self.fm_print.place(x=10, y=740)
        self.fm_show1 = Frame(self.root, height=480, width=860, relief='ridge', bd=5, bg=self.bg)
        self.fm_show1.place(x=415, y=10)
        self.fm_show2 = Frame(self.root, height=480, width=860, relief='ridge', bd=5, bg=self.bg)
        self.fm_show2.place(x=415, y=500)

        self.master_map = {'fm_args': self.fm_args, 'fm_print': self.fm_print}

        # -----------------------配置---boxes---组件参数-------------------------
        self.most_box_args = {'master': self.fm_args, 'width': 9, }
        self.box_args = {
            'metrics': {'master': self.fm_args, 'width': 12, },
            'metrics_idx': {'master': self.fm_args, 'width': 12, },
            'y_names': {'master': self.fm_args, 'width': 25, },
            'method': {'master': self.fm_args, 'width': 30, },
            'cb_number': {'master': self.fm_args, 'width': 10, },
            'select_feature': {'master': self.fm_args, 'width': 24},
            'select_x_pkl': {'master': self.fm_args, 'width': 28},
        }
        self.box_value_args = {
            'metrics': list(self.metrics.keys()), 'metrics_idx': list(range(30)),
            'y_names': list(self.path_data_dict.keys()),
            'method': ['auto', 'abs', 'sigma3', 'diff', 'trend'],
            'cb_number': list(range(5, 150, 10)),
            'select_feature': self.select_feature,
            'select_x_pkl': input_x_pkls(),
        }
        self.box_value_type_args = ['period1', 'period2', 'period3']
        self.box_place_args = {
            'metrics': {'x': 70, 'y': 100},
            'metrics_idx': {'x': 260, 'y': 100},
            'y_names': {'x': 70, 'y': 160},
            'method': {'x': 70, 'y': 200},
            'cb_number': {'x': 15, 'y': 530},
            'select_feature': {'x': 120, 'y': 280},
            'select_x_pkl': {'x': 130, 'y': 420},
        }
        self.button_command_args = {
            'show': self._plot,
            'correct': self._correct,
            'clear_m_cache': self._clear_m_cache,
            'save_monitor': self._save_monitor,
            'upper_plot': self.upper_plot,
            'lower_plot': self.lower_plot,
            'download': self.save_all_img,
            'monitor_to_mysql': self._monitor_to_mysql,
        }
        # ------------配置---spin---组件参数----------------------------------
        t_li = [str(t)[:10] for t in date_range('2018-01-31', '2021-12-31', freq='M')]
        self.spin_args = {
            'end_datetime': {
                'master': self.fm_args,
                'values': t_li,
                'width': 10},
            'fd_dimension': {'master': self.fm_args,
                             'values': [s / 100 for s in range(100, 175)] + [2.0, 2.5, 4.0, 8.0],
                             'width': 8},
        }
        self.spin_command_args = {
            'end_datetime': self._plot,
            'fd_dimension': self._plot,
        }
        self.spin_place_args = {
            'end_datetime': {'x': 70, 'y': 240},
            'fd_dimension': {'x': 270, 'y': 240},
        }
        self._ini_all()

    def _basic_ini_(self):
        self.path_data_dict = get_all_collector()
        self.data = read_pickle(self.path_data_dict[list(self.path_data_dict.keys())[0]])
        self.md_number = len(self.data['dict'])

    def _on_key_press1(self, event):
        print("you pressed {}".format(event.key))
        key_press_handler(event, self.canvas1, self.toolbar1)

    def _on_key_press2(self, event):
        print("you pressed {}".format(event.key))
        key_press_handler(event, self.canvas2, self.toolbar2)

    def _ini_all(self):
        self._ini_data()
        # -----------------初始化label,button,box,text,spin---------------------
        self.all_labels = self._label_ini()
        self.all_buttons = self._button_ini()
        self.all_boxs = self._box_ini()
        self._box_current_ini()
        self.all_texts = self._text_ini()
        self.all_spins = self._spin_ini()
        self._spin_value_ini()  # s pin组件还需要开始初始化一些值
        self._ini_summary()

        self.fig1, self.canvas1, self.toolbar1 = self._fig_ini(self.fm_show1, self._on_key_press1)
        self.fig2, self.canvas2, self.toolbar2 = self._fig_ini(self.fm_show2, self._on_key_press2)

    @staticmethod
    def _fig_ini(fm, on_key_press):
        fig = Figure(figsize=(14, 4), dpi=100)
        canvas = FigureCanvasTkAgg(fig, fm)
        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        toolbar = NavigationToolbar2Tk(canvas, fm)
        toolbar.update()
        canvas.mpl_connect("key_press_event", on_key_press)
        return fig, canvas, toolbar

    def _ini_data(self):
        for name in ['df', 'forecast']:
            self.data[name].index = [str(s) for s in self.data[name].index]
        new_dict = {}
        for k, v in self.data['dict'].items():
            new_dict[str(k)] = v
        self.data['dict'] = new_dict

    def _label_ini(self):
        all_labels = {}
        for k, v in self.config['label_place_args'].items():
            self.config['label_args'][k]['master'] = self.master_map[self.config['label_args'][k]['master']]
            all_labels[k] = Label(**self.config['label_args'][k], bg=self.bg, font=self.t_f)
            all_labels[k].place(**v)  # 放位置
        return all_labels

    def _text_ini(self, all_texts={}):
        for k, v in self.config['text_place_args'].items():
            self.config['text_args'][k]['master'] = self.master_map[self.config['text_args'][k]['master']]
            all_texts[k] = Text(**self.config['text_args'][k], font=self.t_f)
            all_texts[k].place(**v)
            all_texts[k].insert(**self.config['text_insert_args'][k])
        return all_texts

    def _box_ini(self, all_box={}, all_v={}):
        for k, v in self.box_place_args.items():
            all_v[k] = StringVar()
            all_box[k] = Combobox(**self.box_args[k], textvariable=all_v[k])
            all_box[k]['values'] = self.box_value_args[k]
            all_box[k].place(**v)  # 放位置
        all_box['y_names'].bind("<<ComboboxSelected>>", self._ini_this_y)
        all_box['select_x_pkl'].bind("<<ComboboxSelected>>", self._ini_x_pkl)
        all_box['metrics_idx'].bind("<<ComboboxSelected>>", self._reset_summary)
        return all_box

    def _spin_ini(self, all_spins={}):
        for k, v in self.spin_place_args.items():
            all_spins[k] = Spinbox(**self.spin_args[k],
                                   command=self.spin_command_args[k])
            all_spins[k].place(**v)
            all_spins[k].index(0)
        all_spins['end_datetime'].bind("<<ComboboxSelected>>", self._plot)
        return all_spins

    def _button_ini(self):
        all_buttons = {}
        for k, v in self.config['button_place_args'].items():
            self.config['button_args'][k]['master'] = self.master_map[self.config['button_args'][k]['master']]
            all_buttons[k] = Button(**self.config['button_args'][k], command=self.button_command_args[k], font=self.t_f)
            all_buttons[k].place(**v)
        return all_buttons

    def _spin_value_ini(self):
        self.all_spins['end_datetime'].delete(0, END)
        self.all_spins['end_datetime'].insert(0, '2018-03-31')
        self.all_spins['fd_dimension'].delete(0, END)
        self.all_spins['fd_dimension'].insert(0, '1.25')

    def _box_current_ini(self):
        self.all_boxs['metrics'].current(1)
        self.all_boxs['metrics_idx'].current(0)
        self.all_boxs['method'].current(3)
        self.all_boxs['y_names'].current(0)

    def _ini_x_pkl(self, event):
        pth = self.all_boxs['select_x_pkl'].get()
        self.x = read_pickle(real_path(pth))

    # ------------------------------------------------------------------------
    # ---------分界线-上面代码主要是用于初始化整个界面，下面代码是触发逻辑---------
    # ------------------------------------------------------------------------

    # ------------初始化选择的y的函数,当切换一个y的时候,本函数会被触发------------
    def _ini_this_y(self, event):
        self.data = read_pickle(self.path_data_dict[self.all_boxs['y_names'].get()])
        self._ini_data()
        s = 'load %s sucess, total model count %d' % (self.data['y_name'], len(self.data['dict']))
        self.all_texts['speech'].delete(1.0, END)
        self.all_texts['speech'].insert(1.0, s)

    # --------初始化feature的函数,lower_plot改变绘图模式的时候,本函数会被触发-----
    def _ini_features(self):
        # end_datetime = self.all_spins['end_datetime'].get()
        end_datetime = '2020-12-31'
        all_features = list(self.summary.loc[end_datetime, 'features'])
        self.select_feature = ['all'] + all_features
        self.all_boxs['select_feature']['values'] = self.select_feature
        self.all_boxs['select_feature'].current(0)

    # ---------根据metreics和metrics_idx获取结构化的dataframe（summary文件)------
    def _reset_summary(self, event):
        k = self.all_boxs['metrics'].get()
        metrics_idx = int(self.all_boxs['metrics_idx'].get())
        v = self.metrics[k]
        summary, _not_use_s = self.read_summary(self.data, k, v, metrics_idx)
        self.summary = summary
        n_features = list(set(summary['n_features'].to_list()))
        periods = list(set(summary['periods'].to_list()))
        s = "n_features, %s, periods, %s" % (str(n_features), str(periods))
        self.all_texts['speech'].delete(1.0, END)
        self.all_texts['speech'].insert(1.0, s)

    def _ini_summary(self):
        k = self.all_boxs['metrics'].get()
        metrics_idx = int(self.all_boxs['metrics_idx'].get())
        v = self.metrics[k]
        summary, _not_use_s = self.read_summary(self.data, k, v, metrics_idx)
        self.summary = summary

    # ---------修正的触发函数-------反复点击会在True和False之间切换---------------
    def _correct(self):
        if self.correct:
            self.correct = False
        else:
            self.correct = True
        s = 'correct is %s, method is %s' % (str(self.correct), self.all_boxs['method'].get())
        self.all_texts['speech'].delete(1.0, END)
        self.all_texts['speech'].insert(1.0, s)

    # --------upper_plot主函数,通过all_texts['upper_plot']来判断绘制哪一种图形----
    def upper_plot(self):
        self.all_texts['upper_plot'].delete(1.0, END)
        if self.upper_plot_args == 'cent':
            self.upper_plot_args = 'monitor'
            self.all_texts['upper_plot'].insert(1.0, 'monitor')
        elif self.upper_plot_args == 'monitor':
            self.upper_plot_args = 'cent'
            self.all_texts['upper_plot'].insert(1.0, 'cent')

    # -------lower_plot主函数,通过all_texts['lower_plot']来判断绘制哪一种图形-----
    def lower_plot(self):
        print("changing lower")
        self.all_texts['lower_plot'].delete(1.0, END)
        if self.lower_plot_args == 'rolling':
            self.lower_plot_args = 'feature'
            self._spin_value_ini()
            self._ini_summary()
            self._ini_features()
            self.all_texts['lower_plot'].insert(1.0, 'feature')
        elif self.lower_plot_args == 'feature':
            self.lower_plot_args = 'fd'
            self.all_texts['lower_plot'].insert(1.0, 'fd')
        else:
            self.lower_plot_args = 'rolling'
            self.all_texts['lower_plot'].insert(1.0, 'rolling')

    # -----主绘图函数,也是很多按钮的触发函数,调用upperplot和lowerplot-------------
    def _plot(self):
        self.fig1.clear()
        self.fig2.clear()
        k = self.all_boxs['metrics'].get()
        metrics_idx = int(self.all_boxs['metrics_idx'].get())
        v = self.metrics[k]
        summary, title_s = self.read_summary(self.data, k, v, metrics_idx)
        self.summary = summary
        # ------------upper----plot--------------------------------------------
        if self.upper_plot_args == 'cent':
            self.ax1 = self.plot_cent(self.fig1, self.data, k, v, summary, metrics_idx, title_s, correct=self.correct)
        else:
            self.ax1 = self.plot_monitor()
        self.plot_vline_by_time(self.ax1)
        # ------------lower----plot--------------------------------------------
        if self.lower_plot_args == 'rolling':
            self.ax2 = self.plot_rolling(self.fig2, self.data, k, v, summary, title_s, correct=self.correct)
        elif self.lower_plot_args == 'feature':
            self.ax2 = self.plot_feature()
        else:
            self.ax2 = self.plot_fd()
        self.plot_vline_by_time(self.ax2)

        self.canvas2.draw()
        self.canvas1.draw()

    # ----蜈蚣图绘制函数,
    def plot_cent(self, fig, data, k, v, summary, metrics_idx, title_s, correct):
        ax = fig.add_subplot(111)
        y_p_df = expend_dimension(summary, 'y_test_predictions', 0)
        y_df = expend_dimension(summary, 'y_test_targets', 0)
        y_p_df, y_df = deepcopy((y_p_df, y_df))
        method = self.all_boxs['method'].get()
        y_se = self.y.loc[:, self.all_boxs['y_names'].get()]
        fd_score = self.all_spins['fd_dimension'].get()
        if len(str(fd_score)) < 2:
            fd_score = 1.25
        else:
            fd_score = float(fd_score)
        y_p_df, y_t_f_df = prepare_y_yp_acc(y_se, y_p_df, y_df, summary,
                                            method, correct, fd_score)
        for c in y_p_df.columns:
            y = y_df.loc[:, c]
            y_p = y_p_df.loc[:, c]
            y = y.dropna(how='all', axis=0)
            y_p = y_p.dropna(how='all', axis=0)
            plot_fill_between(ax, y.index, y, y_p, y_t_f_df.loc[c, 'acc'])
        ax.plot(y_p_df, marker='D')
        ax.set_title(k + '>>_with_index_' + str(metrics_idx) + title_s, fontsize=12)
        return ax

    # ----滚动预测图绘制函数
    def plot_rolling(self, fig, data, k, v, summary, title_s, correct=False):
        ax = fig.add_subplot(111)
        summary.index = to_datetime(summary.index)
        y_s = summary['test_0y']
        y_fs = summary['test_0y_p']
        ax.plot(y_s, color='black', label='y_real')
        ax.plot(y_fs, color='blue', label='y_forecast')
        if correct:
            method = self.all_boxs['method'].get()
            if method == 'auto':
                print(666)
            else:
                ax.plot(summary['upper_' + method], color='red')
                ax.plot(summary['lower_' + method], color='red')
                summary['mid'] = (summary['upper_' + method] + summary['lower_' + method]) / 2
                ax.plot(summary['mid'], color='gray')
        ax.legend(loc='upper left')
        ax.set_title('rolling' + title_s)
        return ax

    def get_monitor_cahe(self):
        method = self.all_boxs['method'].get()
        basic_str = self.all_boxs['y_names'].get() + '_'
        basic_str = basic_str + method + '_' + self.all_boxs['metrics'].get() + '_'
        basic_str = basic_str + str(self.all_boxs['metrics_idx'].get()) + '.pkl'
        path = '../../output/monitor/' + basic_str
        return path

    # ----还原（监测,可能日度,可能月度）绘制函数
    def plot_monitor(self):
        method = self.all_boxs['method'].get()
        path = self.get_monitor_cahe()
        fd_threhold = float(self.all_spins['fd_dimension'].get())
        if os.path.exists(path):  # 第一加载的时候计算并保存,后面就可以快速读取了
            print('loading existed files', path)
            hf_dict = load_pickle(path)
            hf_df = hf_dict['hf_df']
            y_month_end = hf_dict['y_month_end']
            ctor = hf_dict['corrector']
        else:
            m = Monitor(self.summary, self.x, self.y, self.data['y_name'])
            hf_df, _not_use = m.get_md_and_tensor()  # 花费时间最长,所以需要保存好
            hf_df.index = to_datetime(hf_df.index)
            # 获取高频扩充的低频值
            y_month_end = get_month_end_real(hf_df, self.y, self.data['y_name'])
            print(y_month_end)
            ctor = Corrector(self.y, hf_df, self.data['y_name'], method,
                             fd_number=15, fd=fd_threhold, correct=self.correct)
            hf_dict = {
                'hf_df': hf_df,
                'y_month_end': y_month_end,
                'corrector': ctor,
                'rolling_pd': m.rolling_pd,
                'name': m.name,
            }
            save_pickle(hf_dict, path, True)
        self.hf_df = hf_df
        corrected_df = ctor.go_correct(fd_threhold, correct=self.correct)
        corrected_df.index = to_datetime(hf_df.index)
        corrected_hf_df = ctor.go_connect()
        corrected_hf_df.index = to_datetime(hf_df.index)
        self.correct_hf_df = corrected_hf_df
        self.corrected_df = corrected_df

        ax = self.fig1.add_subplot(111)
        ax.plot(y_month_end, marker='D', color='black', markersize=4)
        ax.plot(hf_df, c='gray', label='raw monitor without method of >>' + method)
        ax.plot(corrected_df, c='pink', label='corrected hf monitor result')
        ax.plot(corrected_hf_df, c='red', label='connected hf monitor result')
        ax.legend()

        return ax

    # ----特征绘制函数---
    def plot_feature(self):
        ax = self.fig2.add_subplot(111)
        # df = pd.DataFrame(self.select_feature)
        choice = self.all_boxs['select_feature'].get()
        end_datetime = self.all_spins['end_datetime'].get()
        self._ini_features()
        if choice == 'all':
            features = self.select_feature[1:]
        else:
            features = [choice]
        for feature in features:
            feature_se = self.x.loc['2018-01-01':, feature]
            ax.plot(feature_se, label=feature)
        ax.axvline(x=to_datetime(end_datetime), ls='--', lw=1)
        ax.legend(loc='upper left')
        ax.set_title('ploting with %s features at %s' %
                     (str(len(features)), end_datetime))
        return ax

    # ----在ax图中绘制一条竖线----
    def plot_vline_by_time(self, ax):
        end_datetime = self.all_spins['end_datetime'].get()
        if len(end_datetime) > 1:
            ax.axvline(x=to_datetime(end_datetime), ls='--', lw=1, c='green')

    # ----绘制分数维度图----
    def plot_fd(self):
        ax = self.fig2.add_subplot(111)
        num_days = 14
        xs = cal_fd(self.y.loc[:, self.all_boxs['y_names'].get()], num_days)
        xs.index = to_datetime(xs.index)
        xss = xs[to_datetime('2018-01-31'):]
        ax.plot(xss, label='fd_dimension_of' + self.all_boxs['y_names'].get())
        fd = self.all_spins['fd_dimension'].get()
        title_s = 'fd:%s at time %s' % (str(fd)[:5], self.all_spins['end_datetime'].get())
        title_s += ' :低于fd(红线)则有可能是处于拐点范围，这时不会按照趋势修正'
        ax.set_title(title_s)
        if len(fd) > 1:
            ax.axhline(y=float(fd), ls='--', lw=1, c='r')
        ax.legend()
        return ax

    # ----保存monitor结果到指定文件夹下----
    def _save_monitor(self):
        y_name = self.data['y_name']
        metrics = self.all_boxs['metrics'].get()
        metrics_idx = int(self.all_boxs['metrics_idx'].get())
        path = askdirectory()
        name = y_name + '_metrics_' + metrics + str(metrics_idx) + '.xlsx'
        df = concat([self.hf_df, self.corrected_df, self.correct_hf_df], axis=1)
        basic_dir = path + '/' + y_name + '/'
        exists(basic_dir)

        latest_md_path = check_path(self.summary['model_path'][-1])
        target_md_path = basic_dir + 'model.' + os.path.split(latest_md_path)[-1].split('.')[-1]
        shutil.copyfile(latest_md_path, target_md_path)
        print('Copy From', latest_md_path)
        print('To', target_md_path)
        df.to_excel(basic_dir + name)
        self.monitor_path = basic_dir + name
        feature_dir = basic_dir + 'feature/'
        exists(feature_dir)  # 生成feature文件夹,保存每一期所需要的特征
        for ii in range(len(self.summary['features'])):
            Series(self.summary['features'][ii]).to_excel(
                feature_dir + name[:-5] + str(ii) + '_latest_features.xlsx')
        save_pickle(self.summary, basic_dir + 'summary.pkl', True)
        save_pickle(self.x.iloc[:5, :], basic_dir + 'x_names_all.pkl', True)
        self.fig1.savefig(basic_dir + 'monitor.png')
        print('保存成功', basic_dir, y_name + 'xlsx', 'summary.pkl')
        show_some_text('文件已保存')

    # 读取summary文件
    def read_summary(self, data, k, v, metrics_idx):
        summary_df = data['df']
        summary_df.sort_values(by=k, ascending=v, inplace=True)
        idx, summary_path = data['dict'][summary_df.index[metrics_idx]]
        print('idx:', idx)
        rolling_m = data['df']
        rolling_m.index = [str(s) for s in rolling_m.index]
        metrics_dict = rolling_m.loc[str(idx), :].to_dict()
        self.metrics_dic = metrics_dict
        s = data['y_name']
        for ks in self.metrics.keys():
            s = s + '【' + ks + '】:' + str(metrics_dict[ks])[:7] + ' '
        print(k, v)
        summary = read_pickle(check_path(summary_path))
        summary.index = summary['end_datetime']
        summary.sort_index(inplace=True)
        return summary, s

    def _clear_m_cache(self):
        path = self.get_monitor_cahe()
        if os.path.exists(path):
            os.remove(path)
            print('已删除', path)

    def _monitor_to_mysql(self):
        pass

    def save_all_img(self):
        y_names = list(self.path_data_dict.keys())
        bench = askfloat(title='输入rolling_acc的阈值', prompt='请输入数字：', initialvalue='0.7')
        print('bench', bench)
        with PdfPages('../../output/all_y_result.pdf') as pdf:
            self.marks = []
            for y_name in y_names:
                k = "test_mae"
                v = self.metrics[k]
                self.data = read_pickle(self.path_data_dict[y_name])
                metrics_idx = 0
                summary, title_s = self.read_summary(self.data, k, v, metrics_idx)
                try:
                    if self.metrics_dic['rolling_acc'] > bench:
                        print(y_name)
                        self.summary = summary
                        self.marks.append(title_s)
                        fig = Figure(figsize=(16, 10))
                        ax = fig.add_subplot(2, 1, 1)
                        y_p_df = expend_dimension(summary, 'y_test_predictions', 0)
                        y_df = expend_dimension(summary, 'y_test_targets', 0)
                        y_p_df, y_df = deepcopy((y_p_df, y_df))
                        method = self.all_boxs['method'].get()
                        y_se = self.y.loc[:, self.all_boxs['y_names'].get()]
                        fd_score = self.all_spins['fd_dimension'].get()
                        correct = False
                        if len(str(fd_score)) < 2:
                            fd_score = 1.25
                        else:
                            fd_score = float(fd_score)
                        y_p_df, y_t_f_df = prepare_y_yp_acc(y_se, y_p_df, y_df, summary,
                                                            method, correct, fd_score)
                        for c in y_p_df.columns:
                            y = y_df.loc[:, c]
                            y_p = y_p_df.loc[:, c]
                            y = y.dropna(how='all', axis=0)
                            y_p = y_p.dropna(how='all', axis=0)
                            plot_fill_between(ax, y.index, y, y_p, y_t_f_df.loc[c, 'acc'])
                        ax.plot(y_p_df, marker='D')
                        title_s = title_s.replace("test_", "")
                        ax.set_title(k + '>>index_' + str(metrics_idx) + title_s, fontsize=12)

                        fd_threhold = float(self.all_spins['fd_dimension'].get())
                        m = Monitor(self.summary, self.x, self.y, self.data['y_name'])
                        hf_df, _not_use = m.get_md_and_tensor()  # 花费时间最长,所以需要保存好
                        hf_df.index = to_datetime(hf_df.index)
                        # 获取高频扩充的低频值
                        y_month_end = get_month_end_real(hf_df, self.y, self.data['y_name'])
                        print(y_month_end)
                        ctor = Corrector(self.y, hf_df, self.data['y_name'], method,
                                         fd_number=15, fd=fd_threhold, correct=self.correct)
                        self.hf_df = hf_df
                        corrected_df = ctor.go_correct(fd_threhold, correct=self.correct)
                        corrected_df.index = to_datetime(hf_df.index)
                        corrected_hf_df = ctor.go_connect()
                        corrected_hf_df.index = to_datetime(hf_df.index)
                        self.correct_hf_df = corrected_hf_df
                        self.corrected_df = corrected_df

                        ax1 = fig.add_subplot(2, 1, 2)
                        ax1.plot(y_month_end, marker='D', color='black', markersize=4)
                        ax1.plot(hf_df, c='gray', label='raw monitor without method of >>' + method)
                        ax1.plot(corrected_df, c='pink', label='corrected hf monitor result')
                        ax1.plot(corrected_hf_df, c='red', label='connected hf monitor result')
                        ax1.legend()
                        pdf.savefig(fig)
                        # self.save_fig[y_name] = fig
                        fig.savefig(f'../../output/plot/{y_name}.jpg', bbox_inches='tight')
                except:
                    print(f"miss {y_name}")

        ind_num = "共%s行业大于%s" % (str(len(y_names)), str(bench))
        save_name = f"../../output/{ind_num}_marked_result.pdf"
        add_bookmark_pdf("../../output/all_y_result.pdf", save_name, self.marks)
        os.remove("../../output/all_y_result.pdf")
        save_pickle(self.save_fig, "../../output/save_fig.pkl", long_str=True)
        print('pdf save done!!!')


def prepare_cb(data, metrics, num=5):
    all_cb = []
    df = data['df']
    for k, v in metrics.items():
        df.sort_values(by=k, ascending=v, inplace=True)
        all_cb += list(df.index[:num])
        print(all_cb)
    return all_cb


def add_bookmark_pdf(address_in, address_out, marks):
    # 读取PDF文件，创建PdfFileReader对象
    book = reader(address_in)
    # 创建PdfFileWriter对象，并用拷贝reader对象进行初始化
    pdf = writer()
    pdf.cloneDocumentFromReader(book)
    # 注意：页数是从0开始的，中文要用unicode字符串，否则会出现乱码
    # 如果这里的页码超过文档的最大页数，会报IndexError异常
    for i, mark in enumerate(marks[:-2]):
        print("i", i, "mark", mark)
        pdf.addBookmark(mark, i)
    # 保存修改后的PDF文件内容到文件中
    # 注意：这里必须用二进制的'wb'模式来写文件，否则写到文件中的内容都为乱码
    with open(address_out, 'wb') as f:
        pdf.write(f)


def get_all_collector():
    dir_path = "../output/collector"
    all_paths = os.listdir(dir_path)
    c_all_path = os.path.join(dir_path, 'all_collector.pkl')
    for path in all_paths:
        if 'all_collector' in path:
            path_data_dict = read_pickle(c_all_path)
            return path_data_dict
    path_data_dict = {}
    for path in all_paths:
        if '.pkl' in path:
            s_path = os.path.join(dir_path, path)
            data = read_pickle(s_path)
            y_name = data['y_name']
            print(y_name, '>', s_path)
            path_data_dict[y_name] = s_path
    save_pickle(path_data_dict, c_all_path, long_str=True)
    return path_data_dict


if __name__ == "__main__":
    form = From()
    form.root.mainloop()
    # config = load_config()
